package org.codefilarete.stalactite.dsl.subentity;

import java.util.Collection;
import java.util.function.Supplier;

import org.codefilarete.reflection.SerializablePropertyAccessor;
import org.codefilarete.reflection.SerializablePropertyMutator;
import org.codefilarete.stalactite.dsl.entity.FluentMappingBuilderOneToManyJoinTableOptions;
import org.codefilarete.stalactite.dsl.relation.OneToManyEntityOptions;
import org.codefilarete.stalactite.sql.ddl.structure.Column;

public interface FluentSubEntityMappingBuilderOneToManyOptions<C, I, O, S extends Collection<O>> extends FluentSubEntityMappingBuilder<C, I>, OneToManyEntityOptions<C, I, O, S> {
	
	/**
	 * {@inheritDoc}
	 * Declaration overridden to adapt return type to this class.
	 *
	 * @param reverseLink opposite owner of the relation (setter)
	 * @return the global mapping configurer
	 */
	@Override
	FluentSubEntityMappingBuilderOneToManyOptions<C, I, O, S> mappedBy(SerializablePropertyMutator<O, ? super C> reverseLink);
	
	/**
	 * {@inheritDoc}
	 * Declaration overridden to adapt return type to this class.
	 *
	 * @param reverseLink opposite owner of the relation (setter)
	 * @return the global mapping configurer
	 */
	@Override
	FluentSubEntityMappingBuilderOneToManyOptions<C, I, O, S> mappedBy(SerializablePropertyAccessor<O, ? super C> reverseLink);
	
	/**
	 * {@inheritDoc}
	 * Declaration overridden to adapt return type to this class.
	 *
	 * @param reverseLink opposite owner of the relation (setter)
	 * @return the global mapping configurer
	 */
	@Override
	FluentSubEntityMappingBuilderOneToManyOptions<C, I, O, S> mappedBy(Column<?, I> reverseLink);
	
	/**
	 * {@inheritDoc}
	 * Declaration overridden to adapt return type to this class.
	 *
	 * @param reverseColumnName opposite owner of the relation
	 * @return the global mapping configurer
	 */
	@Override
	FluentSubEntityMappingBuilderOneToManyOptions<C, I, O, S> reverseJoinColumn(String reverseColumnName);
	
	/**
	 * {@inheritDoc}
	 * Declaration overridden to adapt return type to this class.
	 *
	 * @param tableName the table name of the association table
	 * @return the global mapping configurer
	 */
	@Override
	FluentMappingBuilderOneToManyJoinTableOptions<C, I, O, S> joinTable(String tableName);
	
	/**
	 * {@inheritDoc}
	 * Declaration overridden to adapt return type to this class.
	 *
	 * @param reverseLink opposite owner of the relation
	 * @return the global mapping configurer
	 */
	@Override
	FluentSubEntityMappingBuilderOneToManyOptions<C, I, O, S> reverselySetBy(SerializablePropertyMutator<O, C> reverseLink);
	
	/**
	 * {@inheritDoc}
	 * Declaration overridden to adapt return type to this class.
	 *
	 * @param collectionFactory a collection factory
	 * @return the global mapping configurer
	 */
	@Override
	FluentSubEntityMappingBuilderOneToManyOptions<C, I, O, S> initializeWith(Supplier<S> collectionFactory);
	
	/**
	 * {@inheritDoc}
	 * Declaration overridden to adapt return type to this class.
	 *
	 * @param relationMode any {@link RelationMode}
	 * @return the global mapping configurer
	 */
	@Override
	FluentSubEntityMappingBuilderOneToManyOptions<C, I, O, S> cascading(RelationMode relationMode);
	
	/**
	 * {@inheritDoc}
	 * Declaration overridden to adapt return type to this class.
	 *
	 * @return the global mapping configurer
	 */
	@Override
	FluentSubEntityMappingBuilderOneToManyOptions<C, I, O, S> fetchSeparately();
	
	/**
	 * {@inheritDoc}
	 * Declaration overridden to adapt return type to this class.
	 *
	 * @param orderingColumn orderingColumn the column to be used for order persistence
	 * @return the global mapping configurer
	 */
	@Override
	FluentSubEntityMappingBuilderOneToManyOptions<C, I, O, S> indexedBy(Column<?, Integer> orderingColumn);
	
	/**
	 * {@inheritDoc}
	 * Declaration overridden to adapt return type to this class.
	 *
	 * @param columnName the column name to be used for order persistence
	 * @return the global mapping configurer
	 */
	@Override
	FluentSubEntityMappingBuilderOneToManyOptions<C, I, O, S> indexedBy(String columnName);
	
	/**
	 * {@inheritDoc}
	 * Declaration overridden to adapt return type to this class.
	 *
	 * @return the global mapping configurer
	 */
	@Override
	FluentSubEntityMappingBuilderOneToManyOptions<C, I, O, S> indexed();
	
}
